{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "dea05059-3046-4fe1-9eea-cbc5a3e07718",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAg4AAAHDCAYAAABMJZLOAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjAsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvlHJYcgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAPdVJREFUeJzt3QeY1FTbxvGH3svSe1O6UkUE7A07oDQRK4iigvJiQVGKFQuCKC92RBFFuqIURQWlqYB0kKb0KrD0Ot91H9/sN9vgsDvsLu7/d12B2SmZTCaT3Dl5cpIhFAqFDAAAwENGnycBAAAIwQEAAHgjOAAAAG8EBwAA4I3gAAAAvBEcAACAN4IDAADwRnAAAADeCA6IuMsuu8xGjx7tbo8fP96qVKkS89gTTzxhb775ptd4Nm/ebF9//bXt27fP0pK33nor0c8wePBg692790nHsXXrVvv777/j3b99+3Zbu3Ztkqbrgw8+sHXr1nk/X9P61VdfJfjYI488YlOnTvUe17hx4+yNN96wPXv2WEr75ptv7Icffoj4eO+//37r2rWr9+d/4YUX7PDhw/Ee69mzp/38888nfP2hQ4cSvH/OnDn20ksvud/CiWzbts3y58/vPYwdO9brcwEJITggIg4cOGDHjx93t7ds2RKzAj169KitX78+5nmrVq1yKzl1WKrnJLSiDUyePNluuOEG27hxo6Uls2bNsl9++SXBx3bv3m3PPfecLV++/ITjGDlypJUtWzZeKJo0aZKVL1/eFi9efMrT1bFjR1u2bJn38z/88EObMmVKgo+NGDHC1qxZ4z2uL774wl5//XXLkSOHnYr27dtbwYIFrVatWokOJUqUcGE0MS+//LINHTo01n2ZM2e2DBkyxBrizptjx47FBNyEaGO9YcOGk34GBUDN+9WrV7tlVfNN77V//3779ddf7dlnn7XffvvN/vzzTzesWLEi1rRoI67PqN9NXHr+U0895cZ1IlmzZnXLnsa1a9eumEH3KbzHvS9jRlb9SLrMyXgtEKNixYqxVrK33nqrGwJacQdGjRrlNq7y6quv2qOPPuo2tAoRWbJkiXnemDFjrHTp0m4Fn9BKX3tpZ511luXLly/W+HPlymXnnHOO9erVy6655hp331133WVDhgyJmRaNt3nz5vb888+7jd1HH31kd999d6J75np9IHv27C4QicKSNlyFChVy054tWza78cYbbcaMGW7QHrj28O64445Y41yyZIldeeWVblrjBocGDRpY9erVE53X2jjpfTJlyhRv46F5qI1DQAHtyJEj7jPmyZMn1vM1Ds27gEKM7tNGV0Mwfo1Tn1OfOyGaFxMnTnStSXrdqdB0VapUyVq1apXocxRu9H0nRtMVd9r0OdQqdPnll7t5ff3117v7wg0fPtxuu+0211Jzzz33xMwDfY8a9Pk1T09E06XvdufOnfb555+75UjTonn23Xff2X/+8x/LmTOnPfnkk245123NSy0TQaC+5JJL3DxU8NKyFC6Yn1q+TiTusnAyBAckB8EBEaGm2rx587oV7hVXXGFdunRxrQVqNVBz78KFC93zHnjgAbex1+PR0dExK0TdP3v27JgVpVau2uhqRXvBBRfEe7+gxUJ7WI0bN3b3Pfzww9a2bVu35/b222+7jcX333/vVsyiDdSnn37qbiuodO7c2a34+/fvHzNeNXnnzp071nupBUC0J6np0sZFK3rtOeozq/VAG0A9FqyQtTEShZsaNWrEBAftxe7du9d+//13u+qqq2zlypXu/jJlyrjPo7CksKPpD2ieaM9cDh48aCVLlkz0e9A8T4iau7t16+amUa1DQcuAQpQ+i+anWkB27NgR8xpNczDdt9xyi/uc4ePTnnA4BQcNialZs6b73HFpQ3uiDaPClZaVcJpmBVWFIX2HCkeadu2ZKxTqeyhWrJiVK1cuJkjFDTVt2rRxhzl0SELLpJYTfU6Ft3CffPJJzG0tK1rOgu9CgVKtClqeNm3a5MKgQoTeq1OnTu7QkVoNdKiiXbt27lBU3I12VFSU+37feecdd1hD49Xr9FsKWtsUMsJfp+Chz5fQ9x/3c1577bWnHCyAE9JFroBIOuuss0JDhgxxt7/66qtQ1apVYx576KGHQi+99NJJx/HUU0+F6tWrF9qzZ4/Xe2pRfvXVV2P+PnToUKhkyZKhu+++2/195513hmrWrBnrNT169AgVLVrU3R48eLAbx86dOxN9j0suucQ9J3zo169fzOO63ahRIzfNx48fT3Act956a7xxaFiyZEnovffeC2XJkiVUt27dmKFSpUqhPHnyxBrHtm3b3HscPnw4dOTIkZghX758oR9//DHWfXqOnrtv3z732hUrViT4/nrv/fv3h44dO+aeV7Zs2dAnn3zi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gDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAAgDeCAwAA8EZwAAAA3ggOAADAG8EBAAB4IzgAAABvBAcAAOCN4AAAALwRHAAA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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "预测类别 (对于特征值 0): [1]\n",
      "预测类别 (对于特征值 -1.5): [-1]\n",
      "预测类别 (对于特征值 2.5): [-1]\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "1. 和函数使用\n",
    "'''\n",
    "\n",
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from sklearn import svm\n",
    "\n",
    "# 设置matplotlib使用支持中文的字体\n",
    "plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体\n",
    "plt.rcParams['axes.unicode_minus'] = False    # 正常显示负号\n",
    "\n",
    "# 训练数据和标签\n",
    "X = np.array([[-1], [1], [-2], [2]])  # 一维数据点\n",
    "y = np.array([1, 1, -1, -1])          # 类别标签\n",
    "\n",
    "# 创建SVM模型并指定RBF核函数\n",
    "clf = svm.SVC(kernel='rbf', gamma=0.5)\n",
    "\n",
    "# 训练模型\n",
    "clf.fit(X, y)\n",
    "\n",
    "def plot_decision_boundary(clf, X, y):\n",
    "    # 创建网格以绘制决策边界\n",
    "    xx = np.linspace(X.min() - 1, X.max() + 1, 300)\n",
    "    yy = np.linspace(-1, 1, 2)  # 因为我们处理的是1D数据，所以只需要两个值即可\n",
    "    \n",
    "    XX, YY = np.meshgrid(xx, yy)\n",
    "    \n",
    "    # 计算决策函数值\n",
    "    Z = clf.decision_function(XX.ravel().reshape(-1, 1))\n",
    "    Z = Z.reshape(XX.shape)  # 确保Z与XX形状一致\n",
    "    \n",
    "    # 绘制决策边界\n",
    "    plt.contourf(XX, YY, Z, levels=[-np.inf, 0, np.inf], colors=('lightblue', 'lightgreen'), alpha=0.5)\n",
    "    \n",
    "    # 绘制支持向量\n",
    "    plt.scatter(clf.support_vectors_, np.zeros_like(clf.support_vectors_), s=200,\n",
    "                facecolors='none', edgecolors='k', label='支持向量')\n",
    "    \n",
    "    # 绘制训练数据点\n",
    "    plt.scatter(X, np.zeros_like(X), c=y, cmap=plt.cm.Paired, marker='|', label='数据点')\n",
    "\n",
    "    plt.title('带有RBF核的支持向量机决策边界')  # 中文标题\n",
    "    plt.xlabel('X')\n",
    "    plt.yticks([])  # 隐藏y轴刻度\n",
    "    plt.legend()\n",
    "    plt.show()\n",
    "\n",
    "plot_decision_boundary(clf, X, y)\n",
    "\n",
    "# 预测新数据点的类别\n",
    "x_new_1 = np.array([[0]])  # 特征值为0\n",
    "prediction_1 = clf.predict(x_new_1)\n",
    "print(\"预测类别 (对于特征值 0):\", prediction_1)\n",
    "\n",
    "x_new_2 = np.array([[-1.5]])  # 特征值为-1.5\n",
    "prediction_2 = clf.predict(x_new_2)\n",
    "print(\"预测类别 (对于特征值 -1.5):\", prediction_2)\n",
    "\n",
    "x_new_3 = np.array([[2.5]])  # 特征值为2.5\n",
    "prediction_3 = clf.predict(x_new_3)\n",
    "print(\"预测类别 (对于特征值 2.5):\", prediction_3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "aa9c974b-796d-4e18-9eae-4c9738d4905b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "向量 2 范数: 3.1622776601683795\n",
      "向量 1 范数: 4.0\n",
      "向量无穷范数: 3.0\n",
      "矩阵 F 范数 3.872983346207417\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "2. 范数\n",
    "'''\n",
    "\n",
    "import numpy as np\n",
    "a = np.array([1.0,3.0])\n",
    "print(\"向量 2 范数:\", np.linalg.norm(a,ord=2))\n",
    "print(\"向量 1 范数:\", np.linalg.norm(a,ord=1))\n",
    "print(\"向量无穷范数:\", np.linalg.norm(a,ord=np.inf))\n",
    "\n",
    "a = np.array([[1.0,3.0],[2.0,1.0]])\n",
    "print(\"矩阵 F 范数\", np.linalg.norm(a,ord=\"fro\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "898c899c-d790-4fa2-9639-47c4d5d3c309",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "特征值: [ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15]\n",
      "特征值: [ 1.61168440e+01 -1.11684397e+00 -1.30367773e-15]\n",
      "特征向量:\n",
      " [[-0.23197069 -0.78583024  0.40824829]\n",
      " [-0.52532209 -0.08675134 -0.81649658]\n",
      " [-0.8186735   0.61232756  0.40824829]]\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "4. 特征值和特征向量\n",
    "'''\n",
    "\n",
    "import numpy as np\n",
    "A = np.array([[1.0,2.0,3.0],\n",
    "[4.0,5.0,6.0],\n",
    "[7.0,8.0,9.0]])\n",
    "# 计算特征值\n",
    "print(\"特征值:\", np.linalg.eigvals(A))\n",
    "# 计算特征值和特征向量\n",
    "eigvals,eigvectors = np.linalg.eig(A)\n",
    "print(\"特征值:\", eigvals)\n",
    "print(\"特征向量:\"+\"\\n\", eigvectors)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "69069452-b633-468e-b1df-64e3edd2667f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始矩阵 A:\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "执行 SVD 分解 :\n",
      "左奇异向量\n",
      "U:\n",
      " [[-0.3863177  -0.92236578]\n",
      " [-0.92236578  0.3863177 ]]\n",
      "对角矩阵.奇异值是非负实数、降序\n",
      "D:\n",
      " [9.508032   0.77286964]\n",
      "右奇异向量\n",
      "V:\n",
      " [[-0.42866713 -0.56630692 -0.7039467 ]\n",
      " [ 0.80596391  0.11238241 -0.58119908]\n",
      " [ 0.40824829 -0.81649658  0.40824829]]\n",
      "\n",
      "U @ Sigma @ V 重建矩阵 from SVD:\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "np.dot(U, np.dot(Sigma, V)) 重建矩阵:\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "\n",
      "\n",
      "a. 仅逆序奇异值（从小到大）:\n",
      "对角矩阵.奇异值升序\n",
      "DS:\n",
      " [0.77286964 9.508032  ]\n",
      "\n",
      "U @ Sigma_sorted @ V 重建矩阵 from SVD:\n",
      " [[-6.94022094 -0.81649658  5.30722778]\n",
      " [ 3.26598632  0.81649658 -1.63299316]]\n",
      "\n",
      "\n",
      "b. 奇异值和奇异向量 一起逆序\n",
      "**** 计算 SVD full_matrices=False\n",
      "原始奇异值 D:\n",
      " [9.508032   0.77286964]\n",
      "原始左奇异向量 U:\n",
      " [[-0.3863177  -0.92236578]\n",
      " [-0.92236578  0.3863177 ]]\n",
      "原始右奇异向量 Vt:\n",
      " [[-0.42866713 -0.56630692 -0.7039467 ]\n",
      " [ 0.80596391  0.11238241 -0.58119908]]\n",
      "升序排列的索引:\n",
      " [1 0]\n",
      "升序排列的奇异值 DS_sorted:\n",
      " [0.77286964 9.508032  ]\n",
      "升序排列的奇异值矩阵 Sigma_sorted:\n",
      " [[0.77286964 0.        ]\n",
      " [0.         9.508032  ]]\n",
      "升序排列的左奇异向量 U_sorted:\n",
      " [[-0.92236578 -0.3863177 ]\n",
      " [ 0.3863177  -0.92236578]]\n",
      "升序排列的右奇异向量 Vt_sorted:\n",
      " [[ 0.80596391  0.11238241 -0.58119908]\n",
      " [-0.42866713 -0.56630692 -0.7039467 ]]\n",
      "重建矩阵 reconstructed_A_sorted:\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "\n",
      "**** 切换为默认：计算 SVD full_matrices=True\n",
      ">>> 左奇异向量 U:\n",
      " [[-0.3863177  -0.92236578]\n",
      " [-0.92236578  0.3863177 ]]\n",
      ">>> 奇异值 D:\n",
      " [9.508032   0.77286964]\n",
      ">>> 右奇异向量 Vt:\n",
      " [[-0.42866713 -0.56630692 -0.7039467 ]\n",
      " [ 0.80596391  0.11238241 -0.58119908]\n",
      " [ 0.40824829 -0.81649658  0.40824829]]\n",
      "\n",
      "奇异值矩阵 Sigma:\n",
      " [[9.508032   0.         0.        ]\n",
      " [0.         0.77286964 0.        ]]\n",
      "重建矩阵 reconstructed_A:\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "5. 奇异值分解\n",
    "'''\n",
    "\n",
    "import numpy as np\n",
    "A = np.array([[1.0,2.0,3.0],\n",
    "[4.0,5.0,6.0]])\n",
    "print(\"原始矩阵 A:\\n\", A)\n",
    "\n",
    "# 执行 SVD 分解\n",
    "print(\"执行 SVD 分解 :\")\n",
    "U,D,V = np.linalg.svd(A)\n",
    "print(\"左奇异向量\\nU:\"+\"\\n\", U)\n",
    "print(\"对角矩阵.奇异值是非负实数、降序\\nD:\"+\"\\n\", D)\n",
    "print(\"右奇异向量\\nV:\"+\"\\n\", V)\n",
    "\n",
    "\n",
    "# 构造 Sigma 矩阵\n",
    "Sigma = np.zeros(A.shape)  # 创建一个与 A 形状相同的零矩阵\n",
    "np.fill_diagonal(Sigma, D)  # 将 D 中的奇异值填充到 Sigma 的对角线上\n",
    "\n",
    "# 验证重构的 A 是否与原始 A 相同\n",
    "# 使用 np.dot 或者 @ 运算符来进行矩阵乘法\n",
    "reconstructed_A = U @ Sigma @ V\n",
    "# 或者使用 np.dot(U, np.dot(Sigma, V))\n",
    "print(\"\\nU @ Sigma @ V 重建矩阵 from SVD:\\n\", reconstructed_A)\n",
    "reconstructed_B = np.dot(U, np.dot(Sigma, V))\n",
    "print(\"np.dot(U, np.dot(Sigma, V)) 重建矩阵:\\n\", reconstructed_B)\n",
    "\n",
    "\n",
    "\n",
    "# a. 仅逆序奇异值（从小到大）\n",
    "print(\"\\n\\na. 仅逆序奇异值（从小到大）:\")\n",
    "DS = np.sort(D)\n",
    "Sigma_sorted = np.zeros(A.shape)  # 创建一个与 A 形状相同的零矩阵\n",
    "np.fill_diagonal(Sigma_sorted, DS)  # 将 D 中的奇异值填充到 Sigma 的对角线上\n",
    "reconstructed_A = U @ Sigma_sorted @ V\n",
    "print(\"对角矩阵.奇异值升序\\nDS:\"+\"\\n\", DS)\n",
    "print(\"\\nU @ Sigma_sorted @ V 重建矩阵 from SVD:\\n\", reconstructed_A)\n",
    "\n",
    "\n",
    "\n",
    "# b. 奇异值和奇异向量 一起逆序\n",
    "print(\"\\n\\nb. 奇异值和奇异向量 一起逆序\")\n",
    "# 计算 SVD\n",
    "print(\"**** 计算 SVD full_matrices=False\")\n",
    "U, D, Vt = np.linalg.svd(A, full_matrices=False)\n",
    "# 打印原始奇异值和奇异向量\n",
    "print(\"原始奇异值 D:\\n\", D)\n",
    "print(\"原始左奇异向量 U:\\n\", U)\n",
    "print(\"原始右奇异向量 Vt:\\n\", Vt)\n",
    "\n",
    "# 奇异值和奇异向量一起升序\n",
    "sorted_indices = np.argsort(D)  # 升序排列的索引\n",
    "print(\"升序排列的索引:\\n\", sorted_indices)\n",
    "\n",
    "# 对奇异值进行升序排列\n",
    "DS_sorted = D[sorted_indices]\n",
    "print(\"升序排列的奇异值 DS_sorted:\\n\", DS_sorted)\n",
    "\n",
    "# 构建升序排列的奇异值矩阵 Sigma_sorted\n",
    "Sigma_sorted = np.diag(DS_sorted)  # 使用 np.diag 创建对角矩阵\n",
    "print(\"升序排列的奇异值矩阵 Sigma_sorted:\\n\", Sigma_sorted)\n",
    "# 根据索引调整 U 和 Vt\n",
    "U_sorted = U[:, sorted_indices]\n",
    "Vt_sorted = Vt[sorted_indices, :]\n",
    "print(\"升序排列的左奇异向量 U_sorted:\\n\", U_sorted)\n",
    "print(\"升序排列的右奇异向量 Vt_sorted:\\n\", Vt_sorted)\n",
    "# 重建矩阵\n",
    "reconstructed_A_sorted = U_sorted @ Sigma_sorted @ Vt_sorted\n",
    "print(\"重建矩阵 reconstructed_A_sorted:\\n\", reconstructed_A_sorted)\n",
    "\n",
    "# 切换为默认\n",
    "print(\"\\n**** 切换为默认：计算 SVD full_matrices=True\")\n",
    "U, D, Vt = np.linalg.svd(A, full_matrices=True)\n",
    "print(\">>> 左奇异向量 U:\\n\", U)\n",
    "print(\">>> 奇异值 D:\\n\", D)\n",
    "print(\">>> 右奇异向量 Vt:\\n\", Vt)\n",
    "# 构建奇异值矩阵 Sigma\n",
    "m, n = A.shape\n",
    "Sigma = np.zeros((m, n))  # 创建一个 m x n 的零矩阵\n",
    "Sigma[:len(D), :len(D)] = np.diag(D)  # 将奇异值填充到 Sigma 的对角线上\n",
    "print(\"\\n奇异值矩阵 Sigma:\\n\", Sigma)\n",
    "# 重建矩阵\n",
    "reconstructed_A = U @ Sigma @ Vt\n",
    "print(\"重建矩阵 reconstructed_A:\\n\", reconstructed_A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "5abf6bc7-d868-4ec3-89fd-aca6e3646efd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "m1: [[1. 3.]\n",
      " [1. 0.]]\n",
      "m2: [[1. 2.]\n",
      " [5. 0.]]\n",
      "按矩阵乘法规则：\n",
      " [[16.  2.]\n",
      " [ 1.  2.]]\n",
      "按逐元素相乘：\n",
      " [[1. 6.]\n",
      " [5. 0.]]\n",
      "按逐元素相乘：\n",
      " [[1. 6.]\n",
      " [5. 0.]]\n",
      "向量内积：\n",
      " 14.0\n"
     ]
    }
   ],
   "source": [
    "'''\n",
    "7. 矩阵乘积\n",
    "'''\n",
    "m1 = np.array([[1.0,3.0],[1.0,0.0]])\n",
    "m2 = np.array([[1.0,2.0],[5.0,0.0]])\n",
    "print(\"m1:\", m1)\n",
    "print(\"m2:\", m2)\n",
    "print(\"按矩阵乘法规则：\"+\"\\n\", np.dot(m1, m2))\n",
    "print(\"按逐元素相乘：\"+\"\\n\", np.multiply(m1, m2))\n",
    "print(\"按逐元素相乘：\"+\"\\n\", m1*m2)\n",
    "v1 = np.array([1.0,2.0])\n",
    "v2 = np.array([4.0,5.0])\n",
    "print(\"向量内积：\"+\"\\n\", np.dot(v1, v2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "845dd7fa-78a7-42ac-ac2f-a66386d823a8",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
